package com.lagou.edu.spring.core.defaults;

import com.lagou.edu.spring.core.BeanDefinition;
import com.lagou.edu.spring.core.BeanDefinitionRegistry;
import com.lagou.edu.spring.core.BeanFactoryPostProcessor;
import com.lagou.edu.spring.exceptions.MySpringException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * bean定义信息注册中心实现
 *
 * @author 大犬
 * @date 2020/3/31
 */
public class DefaultBeanDefinitionRegistry implements BeanDefinitionRegistry {

    private Map<String, BeanDefinition> beanDefinitionNameMap;

    private boolean freeze;

    public DefaultBeanDefinitionRegistry() {
        beanDefinitionNameMap = new HashMap<>(10);
        freeze = false;
    }

    @Override
    public void register(String beanName, BeanDefinition beanDefinition) {
        if (freeze) {
            throw new MySpringException("beanDefinitionRegistry was already be freezen");
        }
        beanDefinition.setBeanName(beanName);
        beanDefinitionNameMap.put(beanName, beanDefinition);
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return beanDefinitionNameMap.get(beanName);
    }

    @Override
    public List<BeanDefinition> getAllBeanDefinitions() {

        return new ArrayList<>(beanDefinitionNameMap.values());
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<BeanDefinition> getBeanDefinitions(Class type) {
        return beanDefinitionNameMap.values().stream()
                .filter(beanDefinition -> type.isAssignableFrom(beanDefinition.getBeanType()))
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getAllBeanNames() {

        return new ArrayList<>(beanDefinitionNameMap.keySet());
    }

    @Override
    public List<String> getBeanNames(Class type) {
        List<BeanDefinition> beanDefinitions = getBeanDefinitions(type);
        if (beanDefinitions == null) {
            return null;
        }
        return beanDefinitions.stream()
                .map(BeanDefinition::getBeanName)
                .collect(Collectors.toList());
    }

    @Override
    public void clear() {
        beanDefinitionNameMap.clear();
    }

    @Override
    public void freeze() {
        freeze = true;
    }
}
